﻿using System;
using System.Linq;
using K9Nano.Dependency;
using K9Nano.MultiTenancy;
using K9Nano.Share.Extensions;
using K9Nano.Share.Text;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;

namespace K9Nano.AspNetCore.MultiTenancy.Resolvers
{
    public class DomainTenantResolveContributor : ITenantResolver, ITransientDependency
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly MultiTenancyOption _multiTenancyOption;
        private readonly ITenantStore _tenantStore;

        public DomainTenantResolveContributor(
            IHttpContextAccessor httpContextAccessor,
            IOptionsMonitor<MultiTenancyOption> multiTenancyAccessor,
            ITenantStore tenantStore)
        {
            _httpContextAccessor = httpContextAccessor;
            _multiTenancyOption = multiTenancyAccessor.CurrentValue;
            _tenantStore = tenantStore;
        }

        public Guid? ResolveTenantId()
        {
            if (string.IsNullOrEmpty(_multiTenancyOption.DomainFormat))
            {
                return null;
            }

            var httpContext = _httpContextAccessor.HttpContext;
            if (httpContext == null)
            {
                return null;
            }

            var hostName = httpContext.Request.Host.Host.RemovePreFix("http://", "https://").RemovePostFix("/");
            var domainFormat = _multiTenancyOption.DomainFormat.RemovePreFix("http://", "https://").Split(':')[0].RemovePostFix("/");
            var result = new FormattedStringValueExtracter().Extract(hostName, domainFormat, true, '/');

            if (!result.IsMatch || !result.Matches.Any())
            {
                return null;
            }

            var tenancyName = result.Matches[0].Value;
            if (string.IsNullOrEmpty(tenancyName))
            {
                return null;
            }

            if (string.Equals(tenancyName, "www", StringComparison.OrdinalIgnoreCase))
            {
                return null;
            }

            var tenantInfo = _tenantStore.Find(tenancyName);

            return tenantInfo?.Id;
        }
    }
}